<?php

use Rootant\Api\Exception\ApiException;
use LucaDegasperi\OAuth2Server\Authorizer;
use Rootant\Api\Exception\ValidationException;

class UserController extends CommonController
{

    protected $email = '';

    public function __construct(Authorizer $authorizer)
    {
        parent::__construct($authorizer);
        $this->beforeFilter('oauth', ['except' => ['store', 'fetchEntry']]);
        $this->beforeFilter('oauth.checkClient', ['only' => 'store']);
        $this->beforeFilter('validation');
        $this->afterFilter('disconnect:secondly', ['only' => ['logout']]);
    }

    private static $_validate = [
        'store' => [
            'email'    => 'required|email|unique:user',
            'password' => 'required|min:6|confirmed',
        ],
    ];

    /**
     * 用户注册
     *
     * @return array
     */
    public function store()
    {
        $email    = Input::get('email');
        $password = Input::get('password');

        $avatarUrl = $this->getAvatarUrl();

        $user = DB::table('user');

        $insertId = $user->insertGetId([
                'password'     => Hash::make($password),
                'avatar_url'   => $avatarUrl,
                'email'        => $email,
                'display_name' => strstr($email, '@', true),
                'created_at'   => date('Y-m-d H:i:s'),
                'updated_at'   => date('Y-m-d H:i:s'),
            ]);
        // store the thrid party user info
        $this->saveThirdPartyUser($email, $password);

        $this->preserve($email, $password);

        return (array) $user->find($insertId);
    }

    protected function getAvatarUrl()
    {
        $avatarUrl = Config::get('imagecache::paths.avatar_url_prefix').'default.png';

        if (!Input::has('avatar_url')) {
            return $avatarUrl;
        }

        $avatar = Input::get('avatar_url');

        if (preg_match('#^http(s)?://#', $avatar) === 1) {
            $storageDir  = 'uploads/images/remove_avatar/';
            $newFileName = time().uniqid().'.png';

            $avatarUrl = MultiplexController::curlDownload($avatar, $storageDir, $newFileName);
        }

        return $avatarUrl;
    }

    protected function preserve($username, $password)
    {
        if (! Input::has('unionid')) {
            return;
        }

        $data = [
            'id' => Input::get('unionid'),
            'username' => $username,
            'password' => $password,
        ];

        $authorization = new Authorization;
        $authorization->createOrUpdate($data);
    }

    protected function saveThirdPartyUser($username, $password)
    {
        if (!Input::has('token')) {
            return;
        }

        $token = Input::get('token');
        if (strlen($token) !== 30) {
            return;
        }

        $insertData = array(
                'token'      => $token,
                'username'   => $username,
                'password'   => $password,
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            );

        DB::table('third_party_user_token')->insert($insertData);
    }

    /**
     * 获取当前用户的信息
     *
     * @return array
     */
    public function show()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        $user = $this->user()->find($uid);
        $user->avatar_url = $this->prependAvatarPrefix($user->avatar_url);

        return (array) $user;
    }

    /**
     * 我的评论
     *
     * @return array
     */
    public function myComment()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        $commentModel = DB::table('article_comment')
            ->where('user_id', $uid)
            ->latest('created_at');
        // 模型增加分页
        MultiplexController::addPagination($commentModel);

        $comments = $commentModel->get();

        $comments = $this->processCommentResponse($comments);

        foreach ($comments as $comment) {
            $comment->article = $this->getArticleById($comment->article_id);

            unset($comment->article_id, $comment->updated_at);
        }

        return $comments;
    }

    /**
     * 我的收藏
     *
     * @return array
     */
    public function myStar()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        $starModel = DB::table('star')
            ->where('user_id', $uid)
            ->orderBy('created_at', 'desc');
        // 数据返回增加分页
        MultiplexController::addPagination($starModel);

        $idArr = $starModel->lists('article_id');

        if (empty($idArr)) {
            return [];
        }

        $articles = array();
        foreach ($idArr as $id) {
            $articles[] = $this->getArticleById($id);
        }

        return $articles;
    }

    /**
     * 我的消息
     *
     * @return array
     */
    public function myInformation()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        $informationModel = DB::table('information')
            ->select('id', 'from_uid', 'from_user_ip', 'created_at', 'content', 'type')
            ->where('to_uid', $uid)
            ->orderBy('created_at', 'desc');
        // 增加数据分页
        MultiplexController::addPagination($informationModel);
        $informations = $informationModel->get();

        return $this->processMyInformation($informations);
    }

    /**
     * 处理我的消息的返回值
     *
     * @param  array $informations 需要返回的数组数据
     * @return array
     */
    protected function processMyInformation($informations)
    {
        foreach ($informations as $v) {
            $this->uid = $v->from_uid;
            $this->uip = $v->from_user_ip;
            $v->user = $this->getOwner();

            if ($v->type === 0) {
                // 消息为系统消息
                $v->content_info = ['system' => $v->content];
            } else {
                // 消息是序列化后的消息，则需要反序列还原原来的消息
                $v->content_info = unserialize($v->content);
            }

            unset($v->content, $v->from_uid, $v->from_user_ip, $v->type);
        }

        return $informations;
    }

    protected function validateModify($uid)
    {
        $rules = array(
                'email'  => 'email|unique:user,email,'.$uid,
                'gender' => 'in:男,女',
            );

        $validator = Validator::make(Input::all(), $rules);

        if ($validator->fails()) {
            throw new ValidationException($validator->messages()->all());
        }
    }

    /**
     * 修改用户的个人信息
     *
     * @return object User
     */
    public function modify()
    {
        $uid = $this->authorizer->getResourceOwnerId();
        // 修改用户信息前的校验
        $this->validateModify($uid);

        $user = User::find($uid);
        $this->email = $user->email;

        $allowedFields = ['avatar_url', 'display_name', 'gender', 'email', 'company'];
        array_walk($allowedFields, function($item) use ($user, $uid) {
            $v = Input::get($item);
            if ($v && $item !== 'avatar_url') {
                $user->$item = $v;
            }
            if ($item === 'email' && Input::has('email')) {
                $this->updateThirdPartyUser($this->email, Input::get('email'));
            }
            if ($item === 'avatar_url' && Input::has('avatar_url')) {
                $user->avatar_url = $this->updateAvatar($uid);
            }
        });

        $user->save();

        return $user;
    }

    /**
     * [updateThirdPartyUser description]
     * @param  string $rawEmail 旧邮箱
     * @param  string $newEmail 新邮箱
     * @return void
     */
    protected function updateThirdPartyUser($rawEmail, $newEmail)
    {
        DB::table('third_party_user_token')
            ->where('username', $rawEmail)
            ->update(array('username' => $newEmail, 'updated_at' => date('Y-m-d H:i:s')));
    }

    /**
     * 更新用户头像
     *
     * @param  string $uid 用户id
     * @return string
     */
    protected function updateAvatar($uid)
    {
        $imageStr = Input::get('avatar_url');

        $subDir = substr($uid, -1);
        $storgePath = Config::get('imagecache::paths.avatar_url_prefix').$subDir;
        $path = public_path().$storgePath;
        $path = str_replace('\\', '/', $path);
        if (!is_dir($path)) {
            @mkdir($path, 0777, true);
        }

        $matchFlag = preg_match('/^(data:\s*image\/(\w+);base64,)/', $imageStr, $matches);
        if (!$matchFlag) {
            throw new ApiException;
        }

        $ext = $matches[2];
        $fileName = $path.'/'.$uid.'.'.$ext;
        $flag = file_put_contents($fileName, base64_decode(str_replace($matches[1], '', $imageStr)));
        if ($flag === false) {
            throw new ValidationException('上传头像发生错误');
        }

        $newAvatarUrl = $storgePath.'/'.$uid.'.'.$ext;
        // update the comment user avatar
        $this->updateCommentUserAvatar($uid, $newAvatarUrl);

        return $newAvatarUrl;
    }

    protected function updateCommentUserAvatar($uid, $newAvatarUrl)
    {
        $content = DB::table('information')
            ->where('to_uid', '=', $uid)
            ->lists('content', 'id');

        if (empty($content)) {
            return;
        }

        foreach ($content as $key => &$value) {
            $origin = unserialize($value);

            $data = $origin['comment'];
            foreach ($data as $v) {
                if (is_object($v) && $v->avatar_url !== '/uploads/images/avatar/default.png') {
                    unset($content[$key]);
                    continue;
                }

                if (is_object($v) && $v->avatar_url === '/uploads/images/avatar/default.png') {
                    $v->avatar_url = $newAvatarUrl;
                }
            }

            $value = serialize(['reply' => $origin['reply'], 'comment' => $data]);
        }
        unset($value);

        foreach ($content as $key => $value) {
            DB::table('information')
                ->where('id', '=', $key)
                ->update(['content' => $value, 'updated_at' => date('Y-m-d H:i:s')]);
        }
    }

    /**
     * 修改用户信息当中的邮箱的唯一性校验 before filter
     *
     * @return void
     */
    public function modifyEmail()
    {
        $email = Input::get('email');
        $currentUserId = $this->authorizer->getResourceOwnerId();

        $outcome = DB::connection('mysql2')->table('user')
            ->where('id', '<>', $currentUserId)
            ->where('email', $email)
            ->first();

        if ($outcome) {
            throw new ValidationException('邮箱已被占用');
        }
    }

    /**
     * 用户注销或退出登录
     *
     */
    public function logout()
    {
        $oauthAccessToken = DB::connection('secondly')->table('oauth_access_tokens');

        $oauthAccessToken->where('id', $this->accessToken)->delete();

        return Response::make('', 204);
    }

    public function fetchEntry($id)
    {
        $authorization = DB::table('authorization')
            ->find($id, ['username', 'password']);

        if (! $authorization) {
            return [];
        }

        return (array) $authorization;
    }
}